In [1]:
# Import necessary libraries
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_wine
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, confusion_matrix
# Week 1 Tasks
# 1. Team Formation: Form groups of three students.
# 2. Dataset Exploration:
# Load the dataset
wine_data = load_wine()
# Explore the dataset
print(wine_data.DESCR)
print(wine_data.feature_names)
print(wine_data.target_names)
C:\Users\fawuz\AppData\Local\Temp\ipykernel_12844\2717267339.py:2: DeprecationWarning:
Pyarrow will become a required dependency of pandas in the next major release of pandas (pandas 3.0),
(to allow more performant data types, such as the Arrow string type, and better interoperability with other libraries)
but was not found to be installed on your system.
If this would cause problems for you,
please provide us feedback at https://github.com/pandas-dev/pandas/issues/54466
import pandas as pd
.. _wine_dataset:
Wine recognition dataset
------------------------
**Data Set Characteristics:**
:Number of Instances: 178
:Number of Attributes: 13 numeric, predictive attributes and the class
:Attribute Information:
- Alcohol
- Malic acid
- Ash
- Alcalinity of ash
- Magnesium
- Total phenols
- Flavanoids
- Nonflavanoid phenols
- Proanthocyanins
- Color intensity
- Hue
- OD280/OD315 of diluted wines
- Proline
- class:
- class_0
- class_1
- class_2
:Summary Statistics:
============================= ==== ===== ======= =====
Min Max Mean SD
============================= ==== ===== ======= =====
Alcohol: 11.0 14.8 13.0 0.8
Malic Acid: 0.74 5.80 2.34 1.12
Ash: 1.36 3.23 2.36 0.27
Alcalinity of Ash: 10.6 30.0 19.5 3.3
Magnesium: 70.0 162.0 99.7 14.3
Total Phenols: 0.98 3.88 2.29 0.63
Flavanoids: 0.34 5.08 2.03 1.00
Nonflavanoid Phenols: 0.13 0.66 0.36 0.12
Proanthocyanins: 0.41 3.58 1.59 0.57
Colour Intensity: 1.3 13.0 5.1 2.3
Hue: 0.48 1.71 0.96 0.23
OD280/OD315 of diluted wines: 1.27 4.00 2.61 0.71
Proline: 278 1680 746 315
============================= ==== ===== ======= =====
:Missing Attribute Values: None
:Class Distribution: class_0 (59), class_1 (71), class_2 (48)
:Creator: R.A. Fisher
:Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)
:Date: July, 1988
This is a copy of UCI ML Wine recognition datasets.
https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data
The data is the results of a chemical analysis of wines grown in the same
region in Italy by three different cultivators. There are thirteen different
measurements taken for different constituents found in the three types of
wine.
Original Owners:
Forina, M. et al, PARVUS -
An Extendible Package for Data Exploration, Classification and Correlation.
Institute of Pharmaceutical and Food Analysis and Technologies,
Via Brigata Salerno, 16147 Genoa, Italy.
Citation:
Lichman, M. (2013). UCI Machine Learning Repository
[https://archive.ics.uci.edu/ml]. Irvine, CA: University of California,
School of Information and Computer Science.
|details-start|
**References**
|details-split|
(1) S. Aeberhard, D. Coomans and O. de Vel,
Comparison of Classifiers in High Dimensional Settings,
Tech. Rep. no. 92-02, (1992), Dept. of Computer Science and Dept. of
Mathematics and Statistics, James Cook University of North Queensland.
(Also submitted to Technometrics).
The data was used with many others for comparing various
classifiers. The classes are separable, though only RDA
has achieved 100% correct classification.
(RDA : 100%, QDA 99.4%, LDA 98.9%, 1NN 96.1% (z-transformed data))
(All results using the leave-one-out technique)
(2) S. Aeberhard, D. Coomans and O. de Vel,
"THE CLASSIFICATION PERFORMANCE OF RDA"
Tech. Rep. no. 92-01, (1992), Dept. of Computer Science and Dept. of
Mathematics and Statistics, James Cook University of North Queensland.
(Also submitted to Journal of Chemometrics).
|details-end|
['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline']
['class_0' 'class_1' 'class_2']
In [2]:
# 3. Data Preprocessing:
# Convert dataset to DataFrame
wine_df = pd.DataFrame(data=wine_data.data, columns=wine_data.feature_names)
wine_df['target'] = wine_data.target
# Check for missing values
print(wine_df.isnull().sum())
# Split the dataset into features (X) and target labels (y)
X = wine_df.drop('target', axis=1)
y = wine_df['target']
# Perform scaling
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
alcohol 0 malic_acid 0 ash 0 alcalinity_of_ash 0 magnesium 0 total_phenols 0 flavanoids 0 nonflavanoid_phenols 0 proanthocyanins 0 color_intensity 0 hue 0 od280/od315_of_diluted_wines 0 proline 0 target 0 dtype: int64
In [3]:
# 4. Train-Test Split:
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# 5. Model 1: Logistic Regression
log_reg_model = LogisticRegression(max_iter=1000)
log_reg_model.fit(X_train, y_train)
Out[3]:
LogisticRegression(max_iter=1000)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
LogisticRegression(max_iter=1000)
In [6]:
# Week 2 Tasks
# 6. Model 2: Decision Trees
dt_model = DecisionTreeClassifier()
dt_model.fit(X_train, y_train)
# 7. Model 3: Support Vector Machines (SVM)
svm_model = SVC()
svm_model.fit(X_train, y_train)
# 8. Model Evaluation:
# Function to evaluate models
def evaluate_model(model, X_test, y_test):
y_pred = model.predict(X_test)
acc = accuracy_score(y_test, y_pred)
prec = precision_score(y_test, y_pred, average='weighted')
rec = recall_score(y_test, y_pred, average='weighted')
f1 = f1_score(y_test, y_pred, average='weighted')
cm = confusion_matrix(y_test, y_pred)
return acc, prec, rec, f1, cm
# Evaluate all three models
log_reg_results = evaluate_model(log_reg_model, X_test, y_test)
dt_results = evaluate_model(dt_model, X_test, y_test)
svm_results = evaluate_model(svm_model, X_test, y_test)
# Print results
print("Logistic Regression Results:")
print("Accuracy:", log_reg_results[0])
print("Precision:", log_reg_results[1])
print("Recall:", log_reg_results[2])
print("F1 Score:", log_reg_results[3])
print("Confusion Matrix:\n", log_reg_results[4])
print("Decision Tree Results:")
print("Accuracy:", dt_results[0])
print("Precision:", dt_results[1])
print("Recall:", dt_results[2])
print("F1 Score:", dt_results[3])
print("Confusion Matrix:\n", dt_results[4])
print("SVM Results:")
print("Accuracy:", svm_results[0])
print("Precision:", svm_results[1])
print("Recall:", svm_results[2])
print("F1 Score:", svm_results[3])
print("Confusion Matrix:\n", svm_results[4])
Logistic Regression Results: Accuracy: 1.0 Precision: 1.0 Recall: 1.0 F1 Score: 1.0 Confusion Matrix: [[14 0 0] [ 0 14 0] [ 0 0 8]] Decision Tree Results: Accuracy: 0.9444444444444444 Precision: 0.9513888888888888 Recall: 0.9444444444444444 F1 Score: 0.9448559670781892 Confusion Matrix: [[13 1 0] [ 0 14 0] [ 0 1 7]] SVM Results: Accuracy: 1.0 Precision: 1.0 Recall: 1.0 F1 Score: 1.0 Confusion Matrix: [[14 0 0] [ 0 14 0] [ 0 0 8]]
In [7]:
# 9. Visualization:
# Function to plot confusion matrix
def plot_confusion_matrix(cm, target_names):
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues", xticklabels=target_names, yticklabels=target_names)
plt.xlabel('Predicted Labels')
plt.ylabel('True Labels')
plt.title('Confusion Matrix')
plt.show()
# Visualize confusion matrix for Logistic Regression
plot_confusion_matrix(log_reg_results[4], wine_data.target_names)
# Visualize confusion matrix for Decision Tree
plot_confusion_matrix(dt_results[4], wine_data.target_names)
# Visualize confusion matrix for SVM
plot_confusion_matrix(svm_results[4], wine_data.target_names)
In [8]:
# 10. Results Analysis:
# Results analysis is already done within the print statements after model evaluation.
# 12. Further Steps:
# Exploratory Data Analysis (EDA):
# Pairplot for feature visualization
sns.pairplot(wine_df, hue='target')
plt.title('Pairplot of Wine Dataset Features')
plt.show()
In [9]:
# Correlation heatmap
plt.figure(figsize=(10, 8))
sns.heatmap(wine_df.corr(), annot=True, cmap='coolwarm')
plt.title('Correlation Heatmap of Wine Dataset Features')
plt.show()
# Countplot for target distribution
plt.figure(figsize=(6, 4))
sns.countplot(x='target', data=wine_df)
plt.title('Target Distribution')
plt.xlabel('Target')
plt.ylabel('Count')
plt.show()
In [10]:
# Generate or collect new data instances
# new instances
new_instances = [
[13.24, 2.59, 2.87, 21.0, 118.0, 2.8, 2.69, 0.39, 1.82, 4.32, 1.04, 2.93, 735.0, 0],
[12.07, 2.16, 2.17, 21.0, 85.0, 2.6, 2.65, 0.37, 1.35, 2.76, 0.86, 3.28, 378.0, 1],
# Add more instances as needed
]
# Convert the new instances to a DataFrame
new_instances_df = pd.DataFrame(new_instances, columns=wine_data.feature_names + ['target'])
# Append new instances to the existing DataFrame
wine_df_updated = pd.concat([wine_df, new_instances_df], ignore_index=True)
# Verify the new instances have been added
print(wine_df_updated.tail())
# Split the updated dataset into features (X) and target labels (y)
X_updated = wine_df_updated.drop('target', axis=1)
y_updated = wine_df_updated['target']
# Perform scaling on the updated features
scaler_updated = StandardScaler()
X_scaled_updated = scaler_updated.fit_transform(X_updated)
# Split the updated scaled data into train and test sets
X_train_updated, X_test_updated, y_train_updated, y_test_updated = train_test_split(X_scaled_updated, y_updated, test_size=0.2, random_state=42)
# Now, you can proceed with retraining and evaluating the models using the updated dataset.
# Visualize the data with scatter plots for each pair of features
num_features = len(wine_df_updated.columns) - 1 # Exclude the target column
for i in range(num_features):
for j in range(i+1, num_features): # Loop starts from i+1 to avoid duplicate pairs and plots on diagonal
plt.figure(figsize=(8, 6))
for target_class in wine_df_updated['target'].unique():
plt.scatter(wine_df_updated[wine_df_updated['target'] == target_class].iloc[:, i],
wine_df_updated[wine_df_updated['target'] == target_class].iloc[:, j],
label=f'Class {target_class}')
plt.scatter(new_instances_df.iloc[:, i], new_instances_df.iloc[:, j], color='black', marker='x', label='New Instances')
plt.xlabel(wine_df_updated.columns[i])
plt.ylabel(wine_df_updated.columns[j])
plt.title(f'{wine_df_updated.columns[i]} vs {wine_df_updated.columns[j]}')
plt.legend()
plt.grid(True)
plt.show()
alcohol malic_acid ash alcalinity_of_ash magnesium total_phenols \
175 13.27 4.28 2.26 20.0 120.0 1.59
176 13.17 2.59 2.37 20.0 120.0 1.65
177 14.13 4.10 2.74 24.5 96.0 2.05
178 13.24 2.59 2.87 21.0 118.0 2.80
179 12.07 2.16 2.17 21.0 85.0 2.60
flavanoids nonflavanoid_phenols proanthocyanins color_intensity hue \
175 0.69 0.43 1.35 10.20 0.59
176 0.68 0.53 1.46 9.30 0.60
177 0.76 0.56 1.35 9.20 0.61
178 2.69 0.39 1.82 4.32 1.04
179 2.65 0.37 1.35 2.76 0.86
od280/od315_of_diluted_wines proline target
175 1.56 835.0 2
176 1.62 840.0 2
177 1.60 560.0 2
178 2.93 735.0 0
179 3.28 378.0 1
In [ ]: